package com.ld.shieldsb.common.core.util.notice.wechat.application;

import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.ld.shieldsb.common.core.model.PropertiesModel;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.util.JsoupUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.notice.wechat.EweChatTokenUtil;
import com.ld.shieldsb.common.core.util.notice.wechat.EweChatTool;
import com.ld.shieldsb.common.core.util.notice.wechat.Type;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogFactory;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogModel;

public class EwechatBasicMsgSender {
    protected static Logger log = LoggerFactory.getLogger(EwechatBasicMsgSender.class);

    public static final String TO_USER = "touser"; // 发送给用户
    public static final String AGENTID = "agentid"; // 企业应用的id，整型。企业内部开发，可在应用的设置页面查看；第三方服务商，可通过接口 获取企业授权信息 获取该参数值
    public static final String CONTENT = "content";
    public static final String TITLE = "title";
    public static final String ENABLE_ID_TRANS = "enable_id_trans"; // 表示是否开启id转译，0表示否，1表示是，默认0
    public static final String ENABLE_DUPLICATE_CHECK = "enable_duplicate_check"; // 支持重复消息检查，1开启:表示在一定时间间隔内，同样内容（请求json）的消息，不会重复收到,时间间隔可通过duplicate_check_interval指定，默认1800秒。
    public static final String DUPLICATE_CHECK_INTERVAL = "duplicate_check_interval"; // 重复消息检查时间间隔，单位秒，默认1800秒最大不超过4小时。

    public static final String INVALID_USER = "invaliduser"; // 企业微信未发送成功的用户
    public static final String RESPONSE_CODE = "response_code"; // 响应码
    public static final String MSGID = "msgid"; // 消息id

    // 撤回消息,&debug=1增加调试
    public static final String URL_RECALL = "https://qyapi.weixin.qq.com/cgi-bin/message/recall?access_token=%s"; // %s为占位符

    public static final String URL_SEND = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s"; // 企业微信token的url，%s为占位符
    public static final String URL_UPDATE_TASKCARD = "https://qyapi.weixin.qq.com/cgi-bin/message/update_taskcard?access_token=%s"; // 企业微信更新任务卡片的url，%s为占位符
    public static final String URL_UPLOAD = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s"; // 企业微信上传文件的url，%s为占位符，type媒体文件类型，分别有图片（image）、语音（voice）、视频（video），普通文件（file）

    public static final String URL_SET_WORKBENCH_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/agent/set_workbench_template?access_token=%s"; // 企业微信设置工作台模板
    // 仅原卡片为 按钮交互型、投票选择型、多项选择型的卡片可以调用本接口更新
    public static final String URL_UPDATE_TEMPLATE_CARD = "https://qyapi.weixin.qq.com/cgi-bin/message/update_template_card?access_token=%s"; // 企业微信更新模板卡片事件的url，%s为占位符

    public static final String UPLOAD_FILE_NAME = "media"; // 上传文件名
    public static final String UPLOAD_RESULT_FILE_ID = "media_id"; // 返回的文件编号

    /**
     * 获取访问token
     * 
     * @Title getAccessToken
     * @author 吕凯
     * @date 2021年4月21日 上午10:12:05
     * @param corpid
     * @param corpsecret
     * @return Result
     */
    public static Result getAccessToken(String corpid, String corpsecret, String agentId) {
        return EweChatTokenUtil.getAccessToken(corpid, corpsecret, agentId);
    }

    /**
     * 获取配置参数
     * 
     * @Title getConfig
     * @author 吕凯
     * @date 2021年4月19日 下午5:14:07
     * @return EweChatApplicationParams
     */
    public static EweChatApplicationParams getConfig() {
        String corpid = PropertiesModel.CONFIG.getString("notice.ewechat.client-id");
        String corpsecret = PropertiesModel.CONFIG.getString("notice.ewechat.client-secret");
        String agentid = PropertiesModel.CONFIG.getString("notice.ewechat.agent-id");
        return new EweChatApplicationParams(corpid, corpsecret, agentid);
    }

    /**
     * 默认参数处理
     * 
     * @Title defaultDataMap
     * @author 吕凯
     * @date 2021年4月20日 上午9:05:37
     * @param agentid
     * @param sendTo
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Map<String,Object>
     */
    public static Map<String, Object> defaultDataMap(String agentid, String sendTo, Integer duplicateCheckInterval) {
        if (duplicateCheckInterval == null) {
            duplicateCheckInterval = 600; // 默认10分钟
        }
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(TO_USER, sendTo); // 指定接收消息的成员，成员ID列表（多个接收者用‘|’分隔，最多支持1000个）。特殊情况：指定为”@all”，则向该企业应用的全部成员发送
        dataMap.put(AGENTID, agentid);

        dataMap.put("safe", 0); // 表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
        dataMap.put(ENABLE_ID_TRANS, 1); // 表示是否开启id转译，0表示否，1表示是，默认0
        dataMap.put(ENABLE_DUPLICATE_CHECK, duplicateCheckInterval > 0 ? 1 : 0); // 支持重复消息检查，1开启:表示在一定时间间隔内，同样内容（请求json）的消息，不会重复收到,时间间隔可通过duplicate_check_interval指定，默认1800秒。
        dataMap.put(DUPLICATE_CHECK_INTERVAL, duplicateCheckInterval); // 重复消息检查时间间隔，单位秒，默认1800秒最大不超过4小时。
        return dataMap;
    }

    /**
     * 根据数据dataMap发送消息
     * 
     * @Title sendMsg
     * @author 吕凯
     * @date 2021年4月19日 下午4:15:02
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param data
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    @SuppressWarnings("unchecked")
    public static Result sendMsg(String corpid, String corpsecret, String agentid, Map<String, Object> data) {
        Result result = getAccessToken(corpid, corpsecret, agentid);
        if (result.getSuccess()) { // 0是成功
            String accessToken = result.getMessage();
            String sendUrl = String.format(URL_SEND, accessToken);
            data.put(AGENTID, agentid); // 防止忘记放入再放一遍
            JSONObject jsonResult = JsoupUtil.sendJson(data, sendUrl, EweChatTool.USER_AGENT, 10000);

            EweChatLogModel.EweChatLogModelBuilder<?, ?> builder = EweChatLogModel.builder();
            String msgType = (String) data.get(EweChatTool.MSG_TYPE);
            Map<String, String> contentMap = (Map<String, String>) data.get(msgType);
            String content = null;
            if (contentMap != null) {
                if (contentMap.containsKey(CONTENT)) {
                    content = contentMap.get(CONTENT);
                } else if (contentMap.containsKey("description")) { // 不存在内容描述
                    content = contentMap.get("description");
                }
            }
            builder.type(EweChatTool.APPLICATION).corpid(corpid).corpsecret(corpsecret).agentid(agentid).token(accessToken).msgType(msgType)
                    .sendTo((String) data.get(TO_USER)).title((String) contentMap.get(TITLE)).content(content).data(data);

            if (jsonResult != null) {
                // 转对象
                EwechatResponse response = JSONObject.toJavaObject(jsonResult, EwechatResponse.class);
                result.setData(response);

//                Integer errcode = jsonResult.getInteger(EweChatTool.ERRCODE);
//                String errmsg = jsonResult.getString(EweChatTool.ERRMSG); // 信息
//                String invaliduser = jsonResult.getString(INVALID_USER); // 未发送成功的用户
//                String responseCode = jsonResult.getString(RESPONSE_CODE); // 响应码
//                String msgId = jsonResult.getString(MSGID); // 响应码
                Integer errcode = response.getErrcode();
                String errmsg = response.getErrmsg(); // 信息
                String invaliduser = response.getInvaliduser(); // 未发送成功的用户
                String responseCode = response.getResponseCode(); // 响应码
                String msgId = response.getMsgid(); // 响应码

                builder.errcode(errcode).errmsg(errmsg).responseCode(responseCode).msgid(msgId).invaliduser(invaliduser);

                result.setMessage(errmsg);
                if (errcode == 0) { // 0是成功
                    result.setSuccess(true);
                    builder.success(EweChatTool.SUCCESS);
                } else {
                    result.setSuccess(false);
                    builder.success(EweChatTool.ERROR);
                    if (StringUtils.isNotEmpty(invaliduser)) {
                        result.setMessage("发送失败的用户：" + invaliduser);
                    }
                }
                log.debug(jsonResult + "");
            }

            EweChatLogFactory.saveLog(builder.build()); // 调用保存日志的方法，没有实现需要具体项目自己实现
        }
        return result;

    }

    /**
     * 撤回消息
     * 
     * @Title recallMsg
     * @author 吕凯
     * @date 2021年9月14日 下午1:57:52
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param msgid
     * @return Result
     */
    public static Result recallMsg(String corpid, String corpsecret, String agentid, String msgid) {
        Result result = getAccessToken(corpid, corpsecret, agentid);
        if (result.getSuccess()) { // 0是成功
            String accessToken = result.getMessage();
            String sendUrl = String.format(URL_RECALL, accessToken);
            Map<String, Object> data = ImmutableMap.of(MSGID, msgid);
            JSONObject jsonResult = JsoupUtil.sendJson(data, sendUrl, EweChatTool.USER_AGENT, 10000);

            EweChatLogModel.EweChatLogModelBuilder<?, ?> builder = EweChatLogModel.builder();

            builder.type(EweChatTool.APPLICATION).corpid(corpid).corpsecret(corpsecret).agentid(agentid).token(accessToken)
                    .msgType(Type.RECALL.value).msgid(msgid).data(data);

            if (jsonResult != null) {
                // 转对象
                EwechatResponse response = JSONObject.toJavaObject(jsonResult, EwechatResponse.class);
                result.setData(response);

                Integer errcode = response.getErrcode();
                String errmsg = response.getErrmsg(); // 信息
                String invaliduser = response.getInvaliduser(); // 未发送成功的用户
                String responseCode = response.getResponseCode(); // 响应码

                builder.errcode(errcode).errmsg(errmsg).responseCode(responseCode).invaliduser(invaliduser);

                result.setMessage(errmsg);
                if (errcode == 0) { // 0是成功
                    result.setSuccess(true);
                    builder.isRecall(EweChatTool.RECALL).recallTime(new Date()).success(EweChatTool.SUCCESS);
                } else {
                    result.setSuccess(false);
                    builder.isRecall(EweChatTool.NOT_RECALL).success(EweChatTool.ERROR);
                    if (StringUtils.isNotEmpty(invaliduser)) {
                        result.setMessage("发送失败的用户：" + invaliduser);
                    }
                }
                log.debug(jsonResult + "");
            }

            EweChatLogFactory.saveLog(builder.build()); // 调用保存日志的方法，没有实现需要具体项目自己实现
        }
        return result;

    }

    public static Result recallMsg(String msgid) {
        EweChatApplicationParams params = getConfig();
        return recallMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), msgid);
    }

    // ===============================================上传文件============================================
    /**
     * 上传文件
     * 
     * @Title uploadFile
     * @author 吕凯
     * @date 2021年4月16日 下午3:06:19
     * @param key
     *            key
     * @param file
     *            文件对象
     * @return JSONObject
     */
    public static final JSONObject uploadFile(String accessToken, File file) {
        /*返回结果：    {
        "errcode": 0,
        "errmsg": ""，
        "type": "image", //媒体文件类型，分别有图片（image）、语音（voice）、视频（video），普通文件(file)
        "media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0", //媒体文件上传后获取的唯一标识，3天内有效
        "created_at": "1380000000" //媒体文件上传时间戳
        }
         */
        String url = String.format(URL_UPLOAD, accessToken, Type.FILE.value);
        return JsoupUtil.uploadFile(url, file, UPLOAD_FILE_NAME);
    }

    /**
     * 上传文件
     * 
     * @Title uploadFile
     * @author 吕凯
     * @date 2021年4月16日 下午3:06:59
     * @param file
     * @return JSONObject
     */
    public static final JSONObject uploadFile(File file) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();

        Result result = getAccessToken(params.getCorpId(), params.getCorpSecret(), params.getAgentId());
        if (result.getSuccess()) {
            return uploadFile(result.getMessage(), file);
        }
        return null;
    }

    /**
     * 上传文件，通过流
     * 
     * @Title uploadFile
     * @author 吕凯
     * @date 2021年4月19日 下午2:40:14
     * @param key
     *            密钥
     * @param inputStream
     * @param fileName
     *            文件名称
     * @return JSONObject
     */
    public static final JSONObject uploadFile(String accessToken, InputStream inputStream, String fileName) {
        String url = String.format(URL_UPLOAD, accessToken, Type.FILE.value);
        return JsoupUtil.upload(url, inputStream, UPLOAD_FILE_NAME, fileName);
    }

    public static final JSONObject uploadFile(InputStream inputStream, String fileName) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();

        Result result = getAccessToken(params.getCorpId(), params.getCorpSecret(), params.getAgentId());
        if (result.getSuccess()) {
            return uploadFile(result.getMessage(), inputStream, fileName);
        }
        return null;
    }

}
